#include "server.h"
#include <errno.h>
#include <netdb.h>
#include <unistd.h>

Server::Server (unsigned int port_number) {

	serv_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (!serv_socket) return;
	max_socket = serv_socket;

	addrinfo local, *local_ptr;
	memset (&local, 0, sizeof (local));
	local.ai_family = AF_INET;
	local.ai_socktype = SOCK_STREAM;
	local.ai_protocol = IPPROTO_TCP;
	local.ai_flags = AI_PASSIVE;

	getaddrinfo ("localhost", "23", &local, &local_ptr);
	bind (serv_socket, (sockaddr *)(local_ptr->ai_addr), sizeof(sockaddr_in));
	listen (serv_socket, SOMAXCONN);

	FD_ZERO (&whole_set);
	FD_SET (serv_socket, &whole_set);

}

Server::~Server () {

	if(serv_socket) close (serv_socket);

}

int Server::Run () {

	if (!serv_socket) return -1;

	for (;;) {

		read_set = whole_set;
		FD_ZERO (&write_set);

		std::map<int, Connection*>::iterator conn_it;
		for (conn_it = connections.begin (); conn_it != connections.end (); ++conn_it)
			if (conn_it->second->IsPendingOutput ()) FD_SET (conn_it->first, &write_set);

		select (max_socket+1, &read_set, &write_set, 0, 0);
		
		for (int isock = 0; isock <= max_socket; ++isock) {

			if (FD_ISSET (isock, &read_set)) {

				if (isock == serv_socket) {

					int client_socket = accept (serv_socket, 0, 0);
					FD_SET (client_socket, &whole_set);
					if (client_socket > max_socket) max_socket = client_socket;
				
					sockaddr_in peer_address;
					socklen_t peer_addr_len = sizeof (peer_address);

					getpeername (client_socket, (sockaddr*)(&peer_address), &peer_addr_len);
					connections [client_socket] = new Connection (inet_ntoa (peer_address.sin_addr));				
#ifdef DEBUG
					printf ("Peer %s connected.\n", connections [client_socket]->GetPeerIP ().c_str ());
#endif

				} else {

					MessageHeader header;
					int len = read (isock, &msg, sizeof (header));
					if (!len) {

#ifdef DEBUG
					printf ("Peer %s disconnected.\n", connections [isock]->GetPeerIP ().c_str ());
#endif		
						FD_CLR (isock, &whole_set);
						delete connections [isock];
						connections.erase (connections.find (isock));
						continue;

					} else {

						

					}

				}

			}

			if (FD_ISSET (isock, &write_set)) {

				

			}

		}
	
	}

	return 0;

}
